// Authors: ARJANEN Loïc & BIVERT Mathieu

using System;
using System.Linq.Expressions;
using System.Collections.Generic;
using System.Text;
using System.Data.SqlClient;
using System.Security.Cryptography;
using System.Reflection;

namespace CompteBancaire
{
    public class AccesBD : IAccesBD
    {
        UTF8Encoding enc;
        SHA512Managed hasher;

        public AccesBD()
        {
            enc = new UTF8Encoding();
            hasher = new SHA512Managed();
        }

        private SqlParameter newParam(String name, String value)
        {
            SqlParameter p;

            p = new SqlParameter();
            p.ParameterName = "@" + name;
            p.Value = value;

            return p;
        }

        private static SqlConnection newConn()
        {
            String cstr = "Data Source=.\\SQLEXPRESS;AttachDbFilename=\"C:\\Documents and Settings\\mathieu\\Mes documents\\test.mdf\";Integrated Security=True;Connect Timeout=30;User Instance=True";

            return new SqlConnection(cstr);
        }

        public static SqlDataReader execute(String query, params Expression<Func<String>>[] exprs)
        {
            using (SqlConnection conn = newConn())
            {
                SqlCommand cmd;

                cmd = new SqlCommand(query, conn);

                if (exprs != null) {
                    foreach (Expression<Func<String>> e in exprs)
                    {
                        var body = ((MemberExpression)e.Body); ;
                        string name = body.Member.Name;
                        var value = ((FieldInfo)body.Member)
                                .GetValue(((ConstantExpression)body.Expression).Value);
                        cmd.Parameters.AddWithValue(name, value);
                    }
                }

                return cmd.ExecuteReader();
            }
        }

        public Utilisateur extraireUtilisateur(String login, byte[] passwd)
        {
            SqlDataReader ret;
            Utilisateur u;

            ret = execute("SELECT * FROM Utilisateurs WHERE"
                    +"login = @login AND passwd = @passwd",
                    (() => login), (() => passwd.ToString()));
            if (ret == null)
                return null;

            ret.Read();
            u = new Utilisateur((int)ret[0], (string)ret[1], (string)ret[2], (string)ret[3],
                                (string)ret[4], (string)ret[5], (string)ret[6],
                                (byte[])ret[7]);
            ret.Close();

            return u;
        }

        public Utilisateur extraireUtilisateur(int n)
        {
            SqlDataReader ret;
            Utilisateur u;
            var id = n.ToString();

            ret = execute("SELECT * FROM Utilisateurs WHERE"
                    +"id = @id", (() => id));
            if (ret == null)
                return null;

            ret.Read();
            u = new Utilisateur((int)ret[0], (string)ret[1], (string)ret[2], (string)ret[3],
                     (string)ret[4], (string)ret[5], (string)ret[6],
                     (byte[])ret[7]);

            ret.Close();
            return u;
        }
        public bool sauverUtilisateur(Utilisateur u)
        {
            SqlDataReader ret;

            ret = execute("UPDATE Utilisateurs VALUES("
                    +u.Id+", "+u.Role+", '"+u.Nom+"', '"+u.Prenom+"', '"
                    +u.Tel+"', '"+u.Addr+"', '"+u.Email+", '"
                    +u.Login+"', '"+u.Passwd+"') WHERE ID = "+u.Id, null);

            return ret != null;
        }

        //Methode d'ajout dans les tables Conseiller, Client, Compte et Historique
        public  bool ajouterConseiller(Conseiller conseiller)
        {
            try
            {
                SqlCommand cmd;
              SqlParameter i, c, l, pass, n, p, t, e, a;

              cmd = new SqlCommand("INSERT INTO Utilisateurs"+
                  "(userID, classe, login, passwd, nom, prenom, tel, email, adresse)"+
                  "VALUES (@id, @classe, @login, @passwd, @nom, @prenom, @tel, @email, @addresse)",
                  newConn());

              l = new SqlParameter();
              l.ParameterName = "@login";
              l.Value = conseiller.User.Login;
              pass = new SqlParameter();
              pass.ParameterName = "@passwd";
              pass.Value = conseiller.User.Passwd;
              i = new SqlParameter();
              i.ParameterName = "@id";
              i.Value = conseiller.User.Id;
              n = new SqlParameter();
              n.ParameterName = "@nom";
              n.Value = conseiller.User.Nom;
              p = new SqlParameter();
              p.ParameterName = "@prenom";
              p.Value = conseiller.User.Prenom;
              c = new SqlParameter();
              c.ParameterName = "@classe";
              c.Value = conseiller.User.Role;
              t = new SqlParameter();
              t.ParameterName = "@tel";
              t.Value = conseiller.User.Tel;
              e = new SqlParameter();
              e.ParameterName = "@email";
              e.Value = conseiller.User.Email;
              a = new SqlParameter();
              a.ParameterName = "@adresse";
              a.Value = conseiller.User.Addr;

              cmd.Parameters.Add(i);
              cmd.Parameters.Add(c);
              cmd.Parameters.Add(l);
              cmd.Parameters.Add(pass);
              cmd.Parameters.Add(n);
              cmd.Parameters.Add(p);
              cmd.Parameters.Add(t);
              cmd.Parameters.Add(e);
              cmd.Parameters.Add(a);

              return cmd.ExecuteNonQuery() != 0;
          }
          catch (Exception e)
          {
              return false;
          }

      }

        /* XXX */
        public bool ajouterClient(int idConseiller, Utilisateur u)
        {
            Client c = new Client(null);
            c.User = u;
            return ajouterClient(idConseiller, c);
        }

      public bool ajouterClient(int idConseiller, Client nouveauClient)
      {
        try {
        SqlCommand cmd;
        SqlParameter i, c, l, pass, n, p, t, e, a, cons;
        
        cmd = new SqlCommand("INSERT INTO Utilisateurs (userID, classe, login, passwd, nom, prenom, tel, email, adresse, gestID) VALUES (@id, @classe, @login, @passwd, @nom, @prenom, @tel, @email, @addresse, @conseiller)");
        
        l = new SqlParameter();
        l.ParameterName = "@login";
        l.Value = nouveauClient.User.Login;
        pass = new SqlParameter();
        pass.ParameterName = "@passwd";
        pass.Value = nouveauClient.User.Passwd;
        i = new SqlParameter();
        i.ParameterName = "@id";
        i.Value = nouveauClient.User.Id;
        n = new SqlParameter();
        n.ParameterName = "@nom";
        n.Value = nouveauClient.User.Nom;
        p = new SqlParameter();
        p.ParameterName = "@prenom";
        p.Value = nouveauClient.User.Prenom;
        c = new SqlParameter();
        c.ParameterName = "@classe";
        c.Value = nouveauClient.User.Role;
        t = new SqlParameter();
        t.ParameterName = "@tel";
        t.Value = nouveauClient.User.Tel;
        e = new SqlParameter();
        e.ParameterName = "@email";
        e.Value = nouveauClient.User.Email;
        a = new SqlParameter();
        a.ParameterName = "@adresse";
        a.Value = nouveauClient.User.Addr;
        cons = new SqlParameter();
        cons.ParameterName = "@conseiller";
        cons.Value = idConseiller;
        
        cmd.Parameters.Add(i);
        cmd.Parameters.Add(c);
        cmd.Parameters.Add(l);
        cmd.Parameters.Add(pass);
        cmd.Parameters.Add(n);
        cmd.Parameters.Add(p);
        cmd.Parameters.Add(t);
        cmd.Parameters.Add(e);
        cmd.Parameters.Add(a);
        cmd.Parameters.Add(cons);
        
        return cmd.ExecuteNonQuery() != 0;
      }
      catch(Exception e) {
        return false;
      }
    }
    
    public bool ajouterCompte(int idClient, Compte nouveauCompte) {
      try {
        SqlCommand cmd;
        SqlParameter i, s, c;
        
        cmd = new SqlCommand("INSERT INTO Compte (compteID, solde, clientID) VALUES (@id, @solde, @client)");
        
        i = new SqlParameter();
        i.ParameterName = "@id";
        i.Value = nouveauCompte.getId();
        s = new SqlParameter();
        s.ParameterName = "@solde";
        s.Value = nouveauCompte.getSolde();
        c = new SqlParameter();
        c.ParameterName = "@client";
        c.Value = idClient;
        
        cmd.Parameters.Add(i);
        cmd.Parameters.Add(s);
        cmd.Parameters.Add(c);
        
        return cmd.ExecuteNonQuery() != 0;
      }
      catch(Exception e) {
        return false;
      }
    }

    public bool ajouterHistorique(int idCompte, Historique historique)
    {
        try
        {
            SqlCommand cmd;
            SqlParameter i, d, s, c;

            cmd = new SqlCommand("INSERT INTO Historique (compteID, opID, solde, date) VALUES (@compte, @id, @solde, @date)");

            i = new SqlParameter();
            i.ParameterName = "@id";
            i.Value = historique.getIdOp();
            d = new SqlParameter();
            d.ParameterName = "@date";
            d.Value = historique.getDate();
            s = new SqlParameter();
            s.ParameterName = "@solde";
            s.Value = historique.getSolde();
            c = new SqlParameter();
            c.ParameterName = "@compte";
            c.Value = idCompte;

            cmd.Parameters.Add(i);
            cmd.Parameters.Add(d);
            cmd.Parameters.Add(s);
            cmd.Parameters.Add(c);

            return cmd.ExecuteNonQuery() != 0;
        }
        catch (Exception e)
        {
            return false;
        }
    }

   
      //Methode pour extraire des tables Conseiller, Client, Compte et Historique
      public  List<Conseiller> extraireConseillers(){return null;}
      public  List<Client> extraireClients(int idConseiller){return null;}
      public  Client extraireClient(int idCompte) {return null;}
      public  List<Compte> extraireComptes(int idClient) {return null;}
      public  Compte extraireCompte(int idCompte) {return null;}
      public  List<Historique> extraireHistorique(int idCompte) {return null;}
      //Methode pour mettre à jour les tables de la BD
      public  bool sauverConseillers(List<Conseiller> conseillers) {return true;}
      public  bool sauverClients(List<Utilisateur> clients, int idConseiller) {return true;}
      public  bool sauverComptes(List<Compte> comptes, int idClient) {return true;}
      public  bool sauverHistorique(List<Historique> historique, int idCompte) {return true;}
      //Methode pour supprimer des données de la BD
      public  bool supprimerClient(int idClient) {return true;}
      public  bool supprimerConseiller(int idConseiller) {return true;}
      public  bool supprimerCompte(int idCompte) {return true;}
      public  bool supprimerHistorique(int idCompte) {return true;}// Supprimer tout l'historique d'un compte bancaire

    }
}